package cn.lijiajia3515.cairo.auth.framework.security.web.authentication.captcha;

import cn.lijiajia3515.cairo.captcha.image.DelegatingImageCaptchaHandler;
import cn.lijiajia3515.cairo.captcha.image.ImageCaptcha;
import cn.lijiajia3515.cairo.captcha.image.ImageCaptchaArgs;
import cn.lijiajia3515.cairo.captcha.image.ImageCaptchaHandler;
import lombok.Setter;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;

/**
 * 校验码 过滤器
 */
public class CaptchaFilter extends AbstractCaptchaFilter {
	/**
	 * 默认过期时间
	 */
	public static final Duration DEFAULT_EXPIRE = Duration.ofMinutes(5);

	/**
	 * 默认宽度
	 */
	private static final int DEFAULT_WIDTH = 200;

	/**
	 * 默认高度
	 */
	private static final int DEFAULT_HEIGHT = 60;

	/**
	 * 图片校验码生成器
	 */
	@Setter
	private ImageCaptchaHandler imageCaptchaHandler = new DelegatingImageCaptchaHandler();

	/**
	 * 图片 宽度 参数
	 */
	@Setter
	private String widthParameterName = "width";

	/**
	 * 图片 高度参数
	 */
	@Setter
	private String heightParameterName = "height";


	public CaptchaFilter(RequestMatcher requestMatcher) {
		super(requestMatcher);
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
		if (requires(request, response)) {
			int width = Optional.ofNullable(request.getParameter(widthParameterName))
				.map(Integer::valueOf).orElse(DEFAULT_WIDTH);
			int height = Optional.ofNullable(request.getParameter(heightParameterName))
				.map(Integer::valueOf).orElse(DEFAULT_HEIGHT);
			ImageCaptcha captcha = imageCaptchaHandler.getCaptcha(ImageCaptchaArgs.builder().width(width).height(height).build());
			HttpSession session = request.getSession(true);
			session.setAttribute(getVerifyCodeAttributeName(), captcha.getCode());
			session.setAttribute(getVerifyCodeExpireAttributeName(), String.valueOf(Instant.now().plus(DEFAULT_EXPIRE).toEpochMilli()));
			response.setContentType(captcha.getDetail().getMediaType().toString());
			response.getOutputStream().write(captcha.getDetail().getBytes());
			return;
		}
		filterChain.doFilter(request, response);
	}


}
